﻿//-----------------------------------------------------------------------
// <copyright file="PublishedExceptionUnitTest.cs" company="CodePlex">
//     Copyright (c) Doug Holland, CodePlex. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace CodePlex.Diagnostics.Contracts
{
    using System;

    using System.IO;

    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Provides unit tests for the <see cref="T:CodePlex.Diagnostics.PublishedException"/> class.
    /// </summary>
    [TestClass]
    public sealed class PublishedExceptionUnitTest
    {
        #region public PublishedExceptionUnitTest()

        /// <summary>
        /// Initializes a new instance of the <see cref="T:PublishedExceptionUnitTest"/> class.
        /// </summary>
        public PublishedExceptionUnitTest()
        {
        }

        #endregion

        #region public TestContext TestContext

        /// <summary>
        /// Gets or sets the test context which provides information about and functionality for the current test run.
        /// </summary>
        public TestContext TestContext
        {
            get;
            set;
        }

        #endregion

        #region public void PublishedExceptionConstructorUnitTest()

        /// <summary>
        /// Ensures that the constructor of the <see cref="T:CodePlex.Diagnostics.PublishedException"/> class is correctly copying the values from the supplied <see cref="T:System.Exception"/> instance.
        /// </summary>
        [TestMethod]
        public void PublishedExceptionConstructorUnitTest()
        {
            PublishedException publishedException = null;

            Guid publicationId = Guid.NewGuid();

            try
            {
                for (int index = 0; index < 10; index++)
                {
                    index /= index;
                }
            }
            catch (DivideByZeroException ex)
            {
                // establish an instance of the PublishedException class based upon the DivideByZeroException encountered above.
                publishedException = new PublishedException(publicationId, ex);

                // ensure the exception is not null.
                Assert.IsNotNull(publicationId);

                // ensure the publication Id of the PublishedException is correct.
                Assert.AreEqual<Guid>(publishedException.PublicationId, publicationId);
            }

            try
            {
                // establish an instance of the BinaryFormatter to use for testing the serialization and deserialization of the PublishedException class.
                IFormatter formatter = new BinaryFormatter() as IFormatter;

                using (MemoryStream stream = new MemoryStream())
                {
                    // serialize the PublishedException into a memory stream.
                    formatter.Serialize(stream, publishedException);

                    // reset the stream position to the beginning of the stream.
                    stream.Seek(0, SeekOrigin.Begin);

                    // read the stream into a byte array.
                    byte[] buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, buffer.Length);

                    // seek to the beginning of the stream.
                    stream.Seek(0, SeekOrigin.Begin);

                    // deserialize the PublishedException from the memory stream.
                    PublishedException deserializedException = formatter.Deserialize(stream) as PublishedException;

                    // ensure the deserialized exception is not null.
                    Assert.IsNotNull(deserializedException);

                    // ensure the publication Id was serialized and deserialized appropriately.
                    Assert.AreEqual<Guid>(deserializedException.PublicationId, publicationId);

                    // ensure the inner exception is not null.
                    Assert.IsNotNull(deserializedException.InnerException);
                }
            }
            catch (SerializationException ex)
            {
                // exception occurred during either serialization or deserialization, unit test fails...
                Assert.Fail(ex.Message);
            }
        }

        #endregion
    }
}
